package gnss

import (
	"dgo/goutils/utils"
	"encoding/binary"
	"fmt"
)

type GnssRangeDecoder struct {
	Week uint16
	Tow  uint32
	Crc  uint32

	OnConvertSign Func_signconvert
	OnObs         func(idx int, yobs *GnssSVSignal, err error)
}

/*
*

	bufl : 44
*/
func (this *GnssRangeDecoder) innerDecodeObs43(buf []byte, obs *GnssSVSignal) error {
	trackval := U4FromBuf(buf[40:])
	/*
			*track =stat&0x1F;
		    *plock =(stat>>10)&1;
		    *parity=(stat>>11)&1;
		    *clock =(stat>>12)&1;
		    satsys =(stat>>16)&7;
		    *halfc =(stat>>28)&1;
		    sigtype=(stat>>21)&0x1F;
	*/
	sys := trackval >> 16 & 7
	signtype := (trackval >> 21) & 0x1F // 0x1F 0001 1111
	plock := utils.GetBitValue0(uint64(trackval), 10)
	clock := utils.GetBitValue0(uint64(trackval), 12)

	/**
	Parity known flag 0 = Not known1 = Known
	*/
	//parity := utils.GetBitValue0(uint64(trackval), 11);

	/**
	Carrier phase measurement 0 = Half Cycle Not Added,	1 = Half Cycle Added
	*/
	//halfc := utils.GetBitValue0(uint64(trackval), 28)

	obs.NaviSys = RangeToNaviSys(byte(sys))
	if obs.NaviSys == SYS_WLNAV {
		obs.NaviSys = SYS_WLNAV
	}
	prn := U2FromBuf(buf)
	//if obs.NaviSys == gnss.SYS_GLO{
	//	prn -= 37;
	//}else if obs.NaviSys == gnss.SYS_BD{
	//	prn -=140;
	//}else if obs.NaviSys == gnss.SYS_SBS{
	//	prn -=119;
	//}
	if obs.NaviSys == SYS_GLO {
		prn -= 37
	} else if obs.NaviSys == SYS_QZS {
		prn -= 192
	}

	if prn <= 0 || prn > 255 {
		return fmt.Errorf("错误的卫星号[%d]", prn)
	}
	obs.SatId = prn

	if this.OnConvertSign != nil {
		obs.SigId = this.OnConvertSign(byte(sys), byte(signtype))
	}

	if obs.SigId == 0 {
		_, obs.SigId = GnssSvSigIdFromRangeSigId(obs.NaviSys, byte(signtype))
	}

	if obs.SigId == 0 {
		return fmt.Errorf("错误的信号类型:%d:%d", obs.NaviSys, signtype)
	}

	obs.PsV = ByteToFloat64(buf[4:])
	obs.PhV = -ByteToFloat64(buf[16:])

	obs.Doppler = float64(ByteToFloat32(buf[28:]))
	obs.Cnr = ByteToFloat32(buf[32:])
	lockt := float64(ByteToFloat32(buf[36:]))
	obs.LkT = int64(lockt * 1000)

	if plock == 0 {
		//obs.PhV = 0
		//obs.Doppler = 0
		obs.LLI = 1
	}

	if clock == 0 {
		obs.PsV = 0
	}

	return nil
}

func (this *GnssRangeDecoder) DecodeHead(packBuf []byte) error {
	this.Week = binary.LittleEndian.Uint16(packBuf[14:])
	this.Tow = binary.LittleEndian.Uint32(packBuf[16:])

	bodyBuf := packBuf[28:]
	bodyl := len(bodyBuf)
	this.Crc = binary.LittleEndian.Uint32(bodyBuf[bodyl-4:])
	crc0 := Crc32(packBuf[:len(packBuf)-4])
	if this.Crc != crc0 {
		return fmt.Errorf("CRC校验异常")
	}

	return nil
}

/*
*

	range_43消息
*/
func (this *GnssRangeDecoder) DecodeMsg43(packBuf []byte, onobs func(idx int, yobs *GnssSVSignal, err error) bool) error {
	bodyBuf := packBuf[28:]
	n := int(binary.LittleEndian.Uint32(bodyBuf))
	l := 4 + n*44
	if len(bodyBuf) < l {
		return fmt.Errorf("oem4 rangeB length error: len=%d nobs=%d", len(packBuf), n)
	}

	byteN := 4
	var obs GnssSVSignal
	for i := 0; i < n; i++ {
		// 初始化
		obs.Reset()
		err := this.innerDecodeObs43(bodyBuf[byteN:], &obs)
		if !onobs(i+1, &obs, err) {
			break
		}
		byteN += 44
	}
	return nil
}
